package edu.qc.cs370.project1;

import java.util.ArrayList;

import javax.swing.JOptionPane;

public class BlackJack {
	private Gui gui;
	private Storage storage;
	private boolean keepPlaying;
	private boolean hasNextPlayer;
	private boolean winnersSelected;
	private int count;

	public static void main(String args[]){
			
		//startGame();
		BlackJack blackJack = new BlackJack();

		// Initialize objects
		Gui gui = new Gui();
		Storage storage = new Storage();
		
		//Letting blackjack know about storage and gui
		blackJack.setStorage(storage);
		blackJack.setGui(gui);
		
		//Letting gui know about storage
		gui.setStorage(storage);

		// start game
		blackJack.startGame();
	}//main
	
	public void setStorage(Storage s)
	{
		storage = s;
	}
	
	public void setGui(Gui g)
	{
		gui = g;
	}
	
	public void startGame()
	{
		keepPlaying=true;
		createPlayers();
		
		makeDeck(storage.getNumberOfPlayers());

		JOptionPane.showMessageDialog(null, "This game is being played with one card being dealt face-down to everyone." +
		"You will only be able to see the face up card(s).");
		while (keepPlaying) {
			// Collect money
			collectMoney();

			// Deal cards
			dealCards();

			// Give each player a turn
			processTurn();

			// Give winners money
			selectWinner();
			//ask player to continue
			keepPlaying = stillPlay();
		}

	}//start
	
	public void dealCards(){
		// Deal to dealer first
		Card card = storage.getDeck().getCard();
		storage.getDealer().insertCard(card);
		card = storage.getDeck().getCard();
		storage.getDealer().insertCard(card);

		// Deal to players
		for (int x = 0; x < this.storage.getNumberOfPlayers(); x++) {
			Player player = storage.getPlayers().get(x);
			count = 0;
			while(count < 2)
			{
				card = storage.getDeck().getCard();
				player.insertCard(card);
				count++;
			}
		}

		gui.refreshDisplay();
	}//dealCards
	
	public void selectWinner(){
		int topScore = 0;
		int topScoreCount = 0;
		ArrayList<Player> winners = new ArrayList<Player>();
		winnersSelected = false;

		//gui.refreshDisplayEnd();

		// Find top score
		for (int x = 0; x < storage.getNumberOfPlayers(); x++) {
			Player player = storage.getPlayers().get(x);
			int score = player.getScore();
			if (score <= 21 && score > topScore) {
				topScore = score;
				topScoreCount = 0;
				winners = new ArrayList<Player>();
			}
			if (score == topScore) {
				topScoreCount++;
				winners.add(player);
				winnersSelected = true;
			}
		}

		//if a person has gotten a natural black jack, they get the money
		
		int winnings;
		if(winnersSelected)
			winnings = storage.getPot() / winners.size();
		else
			winnings = storage.getPot();
		
//		gui.displayMessage("Found " + winners.size() + " Winner(s)");
		String s = "There are " + winners.size() + " winners.\n";
		boolean naturalBlackJack = false;
		for(int i = 0; i < winners.size(); i++)
		{
			if(winners.get(i).showHand().size() == 2 && winners.get(i).getScore() == 21)
			{
				naturalBlackJack = true;
				Player player = winners.get(i);
				player.setMoney(player.getMoney() + winnings);
				if(winners.size() == 1)
					gui.displayMessage("There is " + winners.size() + " winner.\n" + player.getName() + " gets $" + winnings);
				else
				{
					s += player.getName() + " gets $" + winnings + "\n";
				}//else
			}
		}
		if(winners.size() != 1)
			gui.displayMessage(s);
		//if it is a tie give money to dealer
		if (storage.getDealer().getScore()  <= 21 && storage.getDealer().getScore() >= topScore && !naturalBlackJack)
		{
			gui.displayMessage("The Dealer has won");
			storage.getDealer().setMoney(storage.getDealer().getMoney()+storage.getPot());
		}
		else if (!winnersSelected)
		{
			//give money to dealer
			gui.displayMessage("There were no winners.\nDealer gets the money by default ");
			storage.getDealer().setMoney(storage.getDealer().getMoney()+storage.getPot());
		}
		else
		{
			// Give money to winners
			for (int x = 0; x < winners.size(); x++) {
				Player player = winners.get(x);
				player.setMoney(player.getMoney() + winnings);
				if(winners.size() == 1)
					gui.displayMessage("There is " + winners.size() + " winner.\n" + player.getName() + " gets $" + winnings);
				else
				{
					s += player.getName() + " gets $" + winnings + "\n";
				}//else
			}
			if(winners.size() != 1 && !naturalBlackJack)
				gui.displayMessage(s);
//			gui.refreshDisplay();
		}
		
		
		
		// Remove players without money
		for (int x = (storage.getNumberOfPlayers()); x > 0; x--) {
			int index = x - 1;
			Player player = storage.getPlayers().get(index);
			if (player.getMoney() <= 0) {
				removePlayer(index);
			} else {
				player.setScore(0);
				player.setHand(new ArrayList<Card>());
			}
		}

		storage.getDealer().setScore(0);
		storage.getDealer().setHand(new ArrayList<Card>());

		if (storage.getNumberOfPlayers() <= 0) {
			this.keepPlaying = false;
		}

		for(int i = 0; i < storage.getNumberOfPlayers(); i++)
			storage.getPlayers().get(i).setStillIn(true);
		storage.getDealer().setStillIn(true);
	}
	
	public void createPlayers(){
		int initialPlayerAmount = 200;
		int numberOfPlayers = gui.askTotalNumberOfPlayers();
		storage.setNumberOfPlayers(numberOfPlayers);
		int numberOfHumanPlayers = 1;
        
		if (numberOfPlayers > 1) {
			numberOfHumanPlayers = gui.askNumberOfHumanPlayers();
		}
		
		// Create human players
		for (int x = 0; x < numberOfHumanPlayers; x++) {
			Player player = new Player();
			player.setPlayerType(0);
			String playerName = gui.getPlayerName();
			player.setName(playerName);
			player.setMoney(initialPlayerAmount);
			player.setScore(0);
			storage.getPlayers().add(player);
		}

		// Create computer players
		for (int x = 0; x < storage.getNumberOfPlayers() - numberOfHumanPlayers; x++) {
			Player player = new Player();
			player.setPlayerType(1);
			String playerName = "Computer " + (x + 1);
			player.setName(playerName);
			player.setMoney(initialPlayerAmount);
			player.setScore(0);
			storage.getPlayers().add(player);
		}

		gui.refreshDisplay();
	}
	
	public void collectMoney(){
		int potMoney = 0;
		storage.setPot(potMoney);
		storage.getDealer().setMoney(storage.getDealer().getMoney() - Storage.ANTE);
		
		potMoney += Storage.ANTE;

		for (int x = storage.getNumberOfPlayers() - 1; x >= 0; x--) {
			Player player = storage.getPlayers().get(x);
			if(player.getMoney() >= Storage.ANTE)
			{
				player.setMoney(player.getMoney() - Storage.ANTE);
				potMoney += Storage.ANTE;
			}
			else
			{
				removePlayer(x);
				if (storage.getNumberOfPlayers() == 0){
					stillPlay();
				}
			}
		}

		storage.setPot(potMoney);
		gui.refreshDisplay();
	}
	
	public void makeDeck(int numOfDecks){	
		storage.createDeck(numOfDecks);
	}
	
	public void processTurn(){
		boolean hit = false;
		hasNextPlayer = false;
		
		//process players turn
		if (storage.getNumberOfPlayers() > 0)
		{
			hasNextPlayer = true;
		}
		
		int x = 0;
		while (hasNextPlayer){
			Player player = storage.getPlayers().get(x);
			if (player.getPlayerType() == 0) {
				hit = gui.askPlayerToHit(player);
				while (hit) {
					Card card = storage.getDeck().getCard();
					player.insertCard(card);
					gui.refreshDisplay();

					if (player.getScore() >= 21) {
						hit = false;
					} else {
						hit = gui.askPlayerToHit(player);
					}
				}
			} else if (player.getPlayerType() == 1) {
				hit = !player.toStay();
				while (hit) {
					if (hit){
						JOptionPane.showMessageDialog(null, "Player " + player.getName()
								+ "\nDecided to Hit");
					}

					Card card = storage.getDeck().getCard();
					player.insertCard(card);
					gui.refreshDisplay();

					if (player.getScore() >= 21) {
						hit = false;
					} else {
						hit = !player.toStay();
					}
				}
				if (!hit){
					JOptionPane.showMessageDialog(null, "Player " + player.getName()
							+ "\nDecided to Stay");
				}

			}
			player.setStillIn(false);
			x++;
			if (x >= storage.getNumberOfPlayers())
			{
				hasNextPlayer = false;
			}
		}
		
		//Process dealer's turn
		Player dealer = storage.getDealer();
		hit = !dealer.toStay();
		while (hit) {
			Card card = storage.getDeck().getCard();
			dealer.insertCard(card);
			gui.refreshDisplay();

			if (dealer.getScore() >= 21) {
				hit = false;
			} else {
				hit = !dealer.toStay();
			}
		}
		dealer.setStillIn(false);
		gui.refreshDisplay();
	}
	
	public boolean stillPlay(){
		// ask player to continue
		if (storage.getNumberOfPlayers() > 0) {
			if(gui.askPlayerToContinue())
				return true;
		} else
			JOptionPane.showMessageDialog(null, "No More Players\n***GAME OVER***");
		
		System.exit(0);
		return false;
	}
	
	public void removePlayer(int index) {
		
		if (storage.getPlayers() == null) {
			return;
		}

		if ((index + 1) > storage.getPlayers().size()) {
			return;
		}

		Player player = storage.getPlayers().get(index);
		JOptionPane.showMessageDialog(null, "  Player " + player.getName()
				+ "\n          REMOVED\n Insufficient Balance");

		storage.getPlayers().remove(index);
		storage.setNumberOfPlayers(storage.getNumberOfPlayers() - 1);
	}
	
}//BlackJack
